from gurobipy import *
import numpy as np
from traffic_engineer import *
from traffic_engineering_class import *

# weight each path greedily, so that weights of all paths between two points sum to 1
# splits traffic among paths based on the relative capacity of the paths. Essentially VLB
class VLBTrafficEngineer(TrafficEngineer):
	def __init__(self, aurora_network, all_interblock_paths):
		TrafficEngineer.__init__(self, aurora_network, all_interblock_paths)
		return

	def get_filename_param(self):
		return "vlb"

	# returns a string description of this class
	def get_string(self):
		return "Oblivious VLB"

	def traffic_engineering_class(self):
		return TrafficEngineeringClass.WCMP

	def compute_path_weights(self, logical_topology_adj_matrix, traffic_matrices):
		nblocks = self.aurora_network.get_num_blocks()
		routing_weights = {}
		for i in range(nblocks):
			for j in range(nblocks):
				if i != j:
					total_path_capacities = 0.
					for path in self.all_interblock_paths[i][j]:
						path_capacity = 10E15
						curr_node = path[0]
						for path_index in range(1, len(path), 1):
							next_node = path[path_index]
							link_capacity = min(self.aurora_network.get_link_capacity(curr_node), self.aurora_network.get_link_capacity(next_node))
							path_capacity = min(path_capacity, logical_topology_adj_matrix[curr_node][next_node] * link_capacity)
							curr_node = next_node
						total_path_capacities += path_capacity
						routing_weights[path] = path_capacity
					for path in self.all_interblock_paths[i][j]:
						if total_path_capacities == 0.:
							routing_weights[path] = 0.
						else:
							routing_weights[path] = routing_weights[path] / total_path_capacities
		return routing_weights